package com.lh.runmanage.controller;

import com.lh.runmanage.dto.ProjAvgDto;
import com.lh.runmanage.model.*;
import com.lh.runmanage.model.InPutParam.*;
import com.lh.runmanage.myenum.ChartEnum;
import com.lh.runmanage.service.ProductService;
import com.lh.runmanage.service.ProjAvgService;
import com.lh.runmanage.service.ProjectAndProductService;
import com.lh.runmanage.service.ProjectService;
import com.lh.runmanage.unit.GetPropertiesClass;
import com.lh.runmanage.unit.LhClass;
import com.lh.runmanage.unit.ResultStruct;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.crypto.Data;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ：梁昊，后端工程师：梁昊
 * @create 2021-07-14 18:12
 * @function
 * @editLog
 */
@RestController
@RequestMapping("/projAvgController")
@Api(value = "项目控制层", description = "系统运行态势平台管理端用户")
public class ProjAvgController {
    @Autowired
    ProjAvgService projAvgService;
    @Autowired
    GetPropertiesClass getPropertiesClass;
    @Autowired
    ProjectService projectService;
    @Autowired
    ProductService productService;
    @Autowired
    ProjectAndProductService projectAndProductService;

    /**
     * 得到项目加权平均值，方法ID：SE2021071418003572858E3E52BF1E8
     *
     * @param proCode     表vou_projAvg,字段名proCode:项目Code（不可重复）
     * @param currentDate 表vou_projAvg,字段名currentDate:统计月数
     * @return 项目加权平均值
     */
    @ApiOperation(value = "得到项目加权平均值[项目加权平均值],方法ID：SE2021071418003572858E3E52BF1E8", notes = "/projAvgController/V1/selectProAvgByProCode?proCode=proCode&currentDate=currentDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "proCode", value = "项目Code（不可重复）", dataType = "String", required = true)
            , @ApiImplicitParam(name = "currentDate", value = "统计月数", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProAvgByProCode")
    public BigDecimal selectProAvgByProCode(@RequestParam(value = "proCode") String proCode
            , @RequestParam(value = "currentDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date currentDate) throws UnsupportedEncodingException {
        if (proCode != null) {
            proCode = proCode.trim();
            if (proCode.getBytes("gbk").length > 100) {
                return BigDecimal.valueOf(0);
            }
        }

        ProjAvgInParam projAvgInParam = new ProjAvgInParam();
        projAvgInParam.setProCode(proCode);
        projAvgInParam.setCurrentDate(currentDate);

        return projAvgService.selectProAvgByProCode(projAvgInParam);
    }

    /**
     * 展示端方法：D8，得到大屏曲线，方法ID：SE20210721135926315539BC76EA64A
     *
     * @return 得到前20个项目的加权平均值，统计方式：月
     */
    @ApiOperation(value = "展示端方法：D8，得到大屏曲线[得到前20个项目的加权平均值，统计方式：月],方法ID：SE20210721135926315539BC76EA64A", notes = "/projAvgController/V1/selectProjAvgD8?id=id&proCode=proCode&totalType=totalType&currentDate=currentDate")
    @PostMapping("/V1/selectProjAvgD8")
    public ResultVO selectProjAvgD8() {
        return getLine("D8", new Date(), new Date(), null, false);
    }

    /**
     * 展示端方法：T3，得到大屏曲线，方法ID：SE20210721135926315539BC76EA64B
     *
     * @return 得到前20个项目的加权平均值，统计方式：月
     */
    @ApiOperation(value = "展示端方法：T3，项目的加权平均值，统计方式：月],方法ID：SE20210721135926315539BC76EA64B", notes = "/projAvgController/V1/selectProjAvgT3?beginDate=beginDate&endDate=endDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "beginDate", value = "开始日期", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProjAvgT3")
    public ResultVO selectProjAvgT3(@RequestParam(value = "beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate) throws ParseException {
        beginDate = LhClass.getFirstDay(beginDate);
        Date endDate = LhClass.getLastDay(beginDate);
        return getLine("T3", beginDate, endDate, null, true);
    }

    /**
     * 展示端方法：P7，得到大屏曲线，方法ID：SE20210721135926315539BC76EA64C
     *
     * @return 得到前20个项目的加权平均值，统计方式：月
     */
    @ApiOperation(value = "展示端方法：P7，项目的加权平均值，统计方式：月],方法ID：SE20210721135926315539BC76EA64C", notes = "/projAvgController/V1/selectProjAvgP7?productId=productId")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "productId", value = "产品ID", dataType = "String", required = true)
            , @ApiImplicitParam(name = "beginDate", value = "开始日期", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProjAvgP7")
    public ResultVO selectProjAvgP7(@RequestParam(value = "productId") String productId
            , @RequestParam(value = "beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate) throws ParseException {
        beginDate = LhClass.getFirstDay(beginDate);
        Date endDate = LhClass.getLastDay(beginDate);
        return getLine("P7", beginDate, endDate, productId, true);
    }

    /**
     * 展示端方法：J8，得到大屏曲线，方法ID：SE20210721135926315539BC76EA64E
     *
     * @return 得到前20个项目的加权平均值，统计方式：月
     */
    @ApiOperation(value = "展示端方法：P7，项目的加权平均值，统计方式：月],方法ID：SE20210721135926315539BC76EA64E", notes = "/projAvgController/V1/selectProjAvgJ8?projectId=projectId")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", dataType = "String", required = true)
            , @ApiImplicitParam(name = "beginDate", value = "开始日期", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProjAvgJ8")
    public ResultVO selectProjAvgJ8(@RequestParam(value = "projectId") String projectId
            , @RequestParam(value = "beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate) throws ParseException {
        beginDate = LhClass.getFirstDay(beginDate);
        Date endDate = LhClass.getLastDay(beginDate);
        return getLine("J8", beginDate, endDate, projectId, true);
    }

    /**
     * @param type         统计业
     * @param beginProDate 开始日期
     * @param endProDate   结束日期
     * @param productId    产品ID
     * @param same         是否加入同比
     * @return
     */
    private ResultVO getLine(String type, Date beginProDate, Date endProDate, String productId, boolean same) {
        final int months = 12;//查倒退一年的
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        LineOrBarModel lineOrBarModel = new LineOrBarModel();
        lineOrBarModel.setChartTitle("加权平均值趋势图");
        List<SeriesDataModel> seriesDataModels;
        List<String> arrayList = new ArrayList<>(months);
        List<String> abscissa = new ArrayList<>(months);
        lineOrBarModel.setAbscissa(abscissa);
        Date endDate = endProDate;
        Calendar calendar = Calendar.getInstance();
        for (int i = 0; i < months; i++) {
            calendar.setTime(endDate);
            calendar.add(Calendar.MONTH, (months - i - 1) * -1);
            Date time = calendar.getTime();
            abscissa.add(i, simpleDateFormat.format(time));
            arrayList.add(simpleDateFormat.format(time));
        }

        final Date beginDate = calendar.getTime();

        List<ProjectD4Model> projectD4Models = null;
        switch (type) {
            case "P7":
                final List<String> list = projectAndProductService.selectProjectListByProductId(productId);
                if (!list.isEmpty()) {
                    final List<ProjectSiteModel> projectSiteModels = projectService.selectProjectSite(list);
                    if (!projectSiteModels.isEmpty()) {
                        projectD4Models = new ArrayList<>(projectSiteModels.size());
                        for (ProjectSiteModel projectSiteModel :
                                projectSiteModels) {
                            ProjectD4Model projectD4Model = new ProjectD4Model();
                            projectD4Model.setId(projectSiteModel.getId());
                            projectD4Model.setProjName(projectSiteModel.getProjName());
                            projectD4Models.add(projectD4Model);
                        }
                    }
                }
                break;
            case "D8":
                projectD4Models = projectService.selectProjectD4OrderBy();
                break;
            case "J8":
                final ProjectBaseAllModel projectBaseAllModel = projectService.selectProjectBaseById(productId);
                if (projectBaseAllModel != null) {
                    projectD4Models = new ArrayList<>(1);
                    ProjectD4Model projectD4Model = new ProjectD4Model();
                    projectD4Model.setId(productId);
                    projectD4Model.setProjName(projectBaseAllModel.getProjName());
                    projectD4Models.add(projectD4Model);
                }
                break;
            case "T3":
                ProjAvgD8InParam projAvgD8InParam = new ProjAvgD8InParam();
                projAvgD8InParam.setBeginDate(beginProDate);
                projAvgD8InParam.setEndDate(endProDate);
                projectD4Models = projectService.selectProjectT2OrderTime(projAvgD8InParam);
                break;
            default:
                projectD4Models = projectService.selectProjectD4OrderBy();
                break;
        }
        if (!projectD4Models.isEmpty() && projectD4Models != null) {
            if (!same)
                seriesDataModels = new ArrayList<>(projectD4Models.size());
            else
                seriesDataModels = new ArrayList<>(projectD4Models.size() * 2);
            for (ProjectD4Model projectD4Model :
                    projectD4Models) {
                SeriesDataModel seriesDataModel = new SeriesDataModel(ChartEnum.LINE);
                seriesDataModel.setSeries(projectD4Model.getProjName());

                final String projectId = projectD4Model.getId();
                List<String> projectList = new ArrayList<>(1);
                projectList.add(projectId);
                ProjAvgD8InParam projAvgD8InParam = new ProjAvgD8InParam();
                projAvgD8InParam.setId(projectList);
                projAvgD8InParam.setBeginDate(beginDate);
                projAvgD8InParam.setEndDate(endDate);
                List<ProjAvgD8Model> projAvgD8Models;
                projAvgD8Models = projAvgService.selectProjAvgD8(projAvgD8InParam);
                if (!projAvgD8Models.isEmpty()) {
                    List<DataModel> nowDataModel = new ArrayList<>(months);
                    for (String monthIndex :
                            arrayList) {
                        List<ProjAvgD8Model> collect = projAvgD8Models.stream().filter(a ->
                                new SimpleDateFormat("yyyy-MM").format(a.getCurrentDate()).equals(monthIndex)
                        ).collect(Collectors.toList());
                        DataModel dataModel = new DataModel();
                        dataModel.setKey(monthIndex);
                        if (collect.size() == 1) {
                            BigDecimal totalValue = collect.get(0).getTotalValue();
                            dataModel.setValue(totalValue);
                        } else
                            dataModel.setValue(BigDecimal.valueOf(0));
                        nowDataModel.add(dataModel);
                    }
                    seriesDataModel.setData(nowDataModel);
                }
                if (seriesDataModel.getData() != null && !seriesDataModel.getData().isEmpty())
                    seriesDataModels.add(seriesDataModel);
            }

            if (same && !projectD4Models.isEmpty() && projectD4Models != null) {
                for (ProjectD4Model projectD4Model :
                        projectD4Models) {
                    SeriesDataModel seriesDataModel = new SeriesDataModel(ChartEnum.LINE);
                    seriesDataModel.setSeries(projectD4Model.getProjName() + "(同比)");

                    final String projectId = projectD4Model.getId();
                    List<String> projectList = new ArrayList<>(1);
                    projectList.add(projectId);
                    ProjAvgD8InParam projAvgD8InParam = new ProjAvgD8InParam();
                    projAvgD8InParam.setId(projectList);
                    calendar.setTime(beginDate);
                    calendar.add(Calendar.MONTH, getPropertiesClass.getWithMonths() * -1);
                    projAvgD8InParam.setBeginDate(calendar.getTime());
                    calendar.setTime(endDate);
                    calendar.add(Calendar.MONTH, getPropertiesClass.getWithMonths() * -1);
                    projAvgD8InParam.setEndDate(calendar.getTime());
                    List<ProjAvgD8Model> projAvgD8Models = projAvgService.selectProjAvgD8(projAvgD8InParam);
                    if (!projAvgD8Models.isEmpty()) {
                        List<DataModel> nowDataModel = new ArrayList<>(months);
                        for (String monthIndex :
                                arrayList) {
                            List<ProjAvgD8Model> collect = projAvgD8Models.stream().filter(a ->
                                    new SimpleDateFormat("yyyy-MM").format(LhClass.getSameCurrentDate(a.getCurrentDate()
                                            , getPropertiesClass.getWithMonths())).equals(monthIndex)
                            ).collect(Collectors.toList());
                            DataModel dataModel = new DataModel();
                            dataModel.setKey(monthIndex);
                            if (collect.size() == 1) {
                                BigDecimal totalValue = collect.get(0).getTotalValue();
                                dataModel.setValue(totalValue);
                            } else
                                dataModel.setValue(BigDecimal.valueOf(0));
                            nowDataModel.add(dataModel);
                        }
                        seriesDataModel.setData(nowDataModel);
                    }
                    if (seriesDataModel.getData() != null && !seriesDataModel.getData().isEmpty())
                        seriesDataModels.add(seriesDataModel);
                }
            }
            lineOrBarModel.setSeriesDataList(seriesDataModels);
        }
        if (arrayList.size() > 0)
            arrayList.clear();
        if (projectD4Models.size() > 0)
            projectD4Models.clear();
        return ResultStruct.success(lineOrBarModel);
    }

    /**
     * 按月、季度、半年、年统计菜单加权平均值，方法ID：SE20210727135129323DD2478089E25
     *
     * @param projectId 表menu_authority,字段名projectCode:项目CODE
     * @param beginDate 表menu_authority,字段名createTime:数据生成时间
     * @param endDate   表menu_authority,字段名createTime:数据生成时间
     * @return 影响条数
     */
    @ApiOperation(value = "展示端：J2，按月、季度、半年、年统计菜单加权平均值[影响条数],方法ID：SE20210727135129323DD2478089E25", notes = "/projAvgController/V1/selectProjAvgByProjectAndTimeGroupBy?projectId=projectId&beginDate=beginDate&endDate=endDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目CODE", dataType = "String", required = true)
            , @ApiImplicitParam(name = "beginDate", value = "数据生成时间", dataType = "Date", required = true)
            , @ApiImplicitParam(name = "endDate", value = "数据生成时间", dataType = "Date")
    })
    @PostMapping("/V1/selectProjAvgByProjectAndTimeGroupByJ2")
    public ResultVO selectProjAvgByProjectAndTimeGroupByJ2(@RequestParam(value = "projectId") String projectId
            , @RequestParam(value = "beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate
            , @RequestParam(value = "endDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) throws ParseException {
        beginDate = LhClass.getFirstDay(beginDate);
        if (endDate == null) {
            endDate = LhClass.getLastDay(beginDate);
        }
        List<String> projectList = new ArrayList<>(1);
        projectList.add(projectId);
        final List<ProjAvgReportModel> menuAuthority = getMenuAuthority(projectList, beginDate, endDate);
        if (!menuAuthority.isEmpty()) {
            final String title = "热度分布图";
            List<SeriesDataModel> seriesDataModels = new ArrayList<>(1);
            SeriesDataModel seriesDataModel = new SeriesDataModel(ChartEnum.BAR);
            seriesDataModel.setSeries("热度分布");
            List<DataModel> dataModels = new ArrayList<>(menuAuthority.size());
            seriesDataModel.setData(dataModels);
            List<String> abscissa = new ArrayList<>(menuAuthority.size());
            for (ProjAvgReportModel projAvgReportModel :
                    menuAuthority) {
                abscissa.add(projAvgReportModel.getMenuName());
                DataModel dataModel = new DataModel();
                dataModel.setKey(projAvgReportModel.getMenuName());
                dataModel.setValue(projAvgReportModel.getWeightNum());
                dataModels.add(dataModel);
            }
            if (seriesDataModel.getData() != null && !seriesDataModel.getData().isEmpty())
                seriesDataModels.add(seriesDataModel);
            final LineOrBarModel lineOrBarModel = getBar(title, seriesDataModels, abscissa);
            return ResultStruct.success(lineOrBarModel);
        } else
            return ResultStruct.success(null);
    }

    private LineOrBarModel getBar(String title, List<SeriesDataModel> seriesDataModels
            , List<String> abscissa) {
        LineOrBarModel lineOrBarModel = new LineOrBarModel();
        lineOrBarModel.setChartTitle(title);
        lineOrBarModel.setAbscissa(abscissa);
        lineOrBarModel.setSeriesDataList(seriesDataModels);
        return lineOrBarModel;
    }

    private List<ProjAvgReportModel> getMenuAuthority(List<String> projectId
            , Date beginDate
            , Date endDate) {
        ProjAvgReportInParam projAvgReportInParam = new ProjAvgReportInParam();
        projAvgReportInParam.setProjectCode(projectId);
        projAvgReportInParam.setBeginTime(beginDate);
        projAvgReportInParam.setEndTime(endDate);

        return projAvgService.selectProjAvgByProjectAndTimeGroupBy(projAvgReportInParam);
    }

    /**
     * 得到项目加权平均值，方法ID：SE202108121816159838438B3D84065
     *
     * @param proCode     表vou_projAvg,字段名proCode:项目Code（不可重复）
     * @param currentDate 表vou_projAvg,字段名currentDate:统计月数
     * @return 根据项目ID
     */
    @ApiOperation(value = "得到项目加权平均值[根据项目ID],方法ID：SE202108121816159838438B3D84065", notes = "/projAvgController/V1/selectProjAvgByProjCode?proCode=proCode&currentDate=currentDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "proCode", value = "项目Code（不可重复）", dataType = "String", required = true, paramType = "query")
            , @ApiImplicitParam(name = "currentDate", value = "统计月数", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProjAvgByProjCode")
    public ResultVO selectProjAvgByProjCode(@RequestParam(value = "proCode") List<String> proCode
            , @RequestParam(value = "currentDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date currentDate) throws UnsupportedEncodingException {

        ProjAvgAllInParam projAvgAllInParam = new ProjAvgAllInParam();
        projAvgAllInParam.setProCode(proCode);
        projAvgAllInParam.setCurrentDate(currentDate);
        final ProjAvgDto projAvgDto = projAvgService.selectProjAvgByProjCode(projAvgAllInParam);
        return ResultStruct.success(projAvgDto);
    }


    /**
     * 得到项目加权平均值，方法ID：SE202108121832347955515CC32318B
     *
     * @param proCode     表vou_projAvg,字段名proCode:项目Code（不可重复）
     * @param totalType   表vou_projAvg,字段名totalType:统计周期(日、周、月、年)
     * @param currentDate 表vou_projAvg,字段名currentDate:统计月数
     * @return 根据项目ID、月数、统计类型
     */
    @ApiOperation(value = "得到项目加权平均值[根据项目ID、月数、统计类型],方法ID：SE202108121832347955515CC32318B", notes = "/projAvgController/V1/selectProjAvgByProjCodeWithOutType?proCode=proCode&totalType=totalType&currentDate=currentDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "proCode", value = "项目Code（不可重复）", dataType = "String", required = true, paramType = "query")
            , @ApiImplicitParam(name = "totalType", value = "统计周期(日、周、月、年)", dataType = "String", required = true)
            , @ApiImplicitParam(name = "currentDate", value = "统计月数", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProjAvgByProjCodeWithOutType")
    public ResultVO selectProjAvgByProjCodeWithOutType(@RequestParam(value = "proCode") List<String> proCode
            , @RequestParam(value = "totalType") String totalType
            , @RequestParam(value = "currentDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date currentDate) throws UnsupportedEncodingException {
        if (totalType != null) {
            totalType = totalType.trim();
            if (totalType.getBytes("gbk").length > 4) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：4", "totalType"), ResultVO.class, null);
            }
        }

        ProjAvgBaseInParam projAvgBaseInParam = new ProjAvgBaseInParam();
        projAvgBaseInParam.setProCode(proCode);
        projAvgBaseInParam.setTotalType(totalType);
        projAvgBaseInParam.setCurrentDate(currentDate);

        return ResultStruct.success(projAvgService.selectProjAvgByProjCodeWithOutType(projAvgBaseInParam));
    }


}